﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using StateMachine;
using System.IO;
using LilTmSimFacade;


namespace TuringMachineTest
{
    class Program
    {
        public static TuringMachine TestMachine;
        public static string InputFileName;
        /// <summary>
        /// Accepts arguments for turing machine jff file and input string / file
        /// </summary>
        /// <param name="args">[machine.jff input [output]][test]</param>
        static void Main(string[] args)
        {
            if (args.Length > 0)
            {
                bool loadResult = false;
                if (args.Length == 1)
                    RunTestMachine();
                else if (args.Length == 2)
                    loadResult = LoadMachine(args[0], args[1]);
                else if (args.Length == 3)
                    loadResult = LoadMachine(args[0], args[1], args[2]);
                else
                    Usage();

				if (loadResult)
				{
					StreamReader reader = new StreamReader(InputFileName);
					string temp;
					Console.WriteLine(TestMachine);
					while (!reader.EndOfStream)
					{
						temp = reader.ReadLine();
						Console.Write("Input: " + temp);
						Console.Write(" Result: " + TestMachine.Run(temp));
						Console.WriteLine(TestMachine.StartState.Transitions.Count);
						Console.WriteLine(" Tape: " + TestMachine.Tape);

					}

				}
				else
				{
					Console.WriteLine("bork");
				}
            }
            else 
            {
                Usage();
            }
            Console.ReadLine();

        }

        public static bool CheckFile(string filename, string filedescription)
        {
            if (!File.Exists(filename))
            {
                Console.WriteLine(filedescription + " file: " + filename + " does not exist!");
                return false;
            }
            else
            {
                return true;
            }
        }

        public static bool LoadMachine(string machine, string input, string output)
        {
            throw new NotImplementedException();

            if (!CheckFile(machine, "Machine") || !CheckFile(input, "Input") || !CheckFile(output, "Output"))
                return false;
            else
            {
                
            }

            
        }

        public static bool LoadMachine(string machine, string input)
        {
            if (!CheckFile(machine, "Machine") || !CheckFile(input, "Input"))
                return false;
            else
            {
                InputFileName = input;
                StateMachineProvider provider = new StateMachineProvider(machine);
                TestMachine = provider.Machine;
                return true;
            }
        }

        public static void Usage()
        {
            Console.WriteLine("Usage: [machine.jff input.txt][test]");
        }

        public static void RunTestMachine()
        {
            TuringMachine t = new TuringMachine();

            State q0 = new State();
            State q1 = new State();
            State q2 = new State();
            State q3 = new State();

            //q0 transitions
            TransitionCollection q0t = new TransitionCollection();
            q0t.Add(new Transition() { Read = '0', Write = '0', Direction = TapeMovement.R, EndState = q0, StartState = q0 });
            q0t.Add(new Transition() { Read = '1', Write = '1', Direction = TapeMovement.R, EndState = q1, StartState = q0 });
            //q1 transitions
            TransitionCollection q1t = new TransitionCollection();
            q1t.Add(new Transition() { Read = '1', Write = '1', Direction = TapeMovement.R, EndState = q1, StartState = q1 });
            q1t.Add(new Transition() { Read = '0', Write = '0', Direction = TapeMovement.R, EndState = q2, StartState = q1 });
            //q2 transitions
            TransitionCollection q2t = new TransitionCollection();
            q2t.Add(new Transition() { Read = '1', Write = '1', Direction = TapeMovement.R, EndState = q3, StartState = q2 });
            q2t.Add(new Transition() { Read = '0', Write = '0', Direction = TapeMovement.R, EndState = q0, StartState = q2 });
            //q3 transitions
            // none!
            q0.IsInitial = true;
            q3.IsFinal = true;

            q0.Transitions = q0t;
            q1.Transitions = q1t;
            q2.Transitions = q2t;
            q3.Transitions = new TransitionCollection();

            t.StartState = q0;
            t.EndState = q3;
            t.States = new StateCollection();
            t.States.Add(q0);
            t.States.Add(q1);
            t.States.Add(q2);
            t.States.Add(q3);

            string[] testStrings = { "0101", "1100", "0000", "1101", "000", "", "111", "1", "0" };
            for (int i = 0; i < testStrings.Length; i++)
            {
                Console.WriteLine("Input: \t\t" + testStrings[i]);
                Console.WriteLine("Result: \t" + t.Run(testStrings[i]));
                Console.WriteLine("Tape: \t\t" + t.Tape);
                Console.WriteLine();
            }
        }
    }
}
